package cn.tedu.storedemo.aop;

import cn.tedu.storedemo.entity.UserEntity;
import cn.tedu.storedemo.entity.UserOpt;
import cn.tedu.storedemo.mapper.CartMapper;
import cn.tedu.storedemo.mapper.ProductMapper;
import cn.tedu.storedemo.mapper.UserOptMapper;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.util.ArrayList;
import java.util.List;

@Component
@Aspect//表示以下为一个切面类，额外采集用户行为的功能，在不改造已有的代码基础上添加该功能，使用aop技术
/*若使用@Aspect注解时，idea没有提示或者导包不了，说明没有对应的架包
需要在pom.xml文件中添加对应的依赖，即：
 <dependency>
            <groupId>aspectj</groupId>
            <artifactId>aspectj-tools</artifactId>
            <version>1.0.6</version>
        </dependency>
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
        </dependency>
  如果xml文件报红，则刷新maven，右键点击报红的依赖，选中maven 选中reload project
* */
public class UserOptAspect {

    public static final String USER_OPT_TYPE_PV="pv";
    public static final String USER_OPT_TYPE_CART="cart";
    public static final String USER_OPT_TYPE_FAV="fav";
    public static final String USER_OPT_TYPE_BUY="buy";

    @Autowired(required = false)
    ProductMapper productMapper;
    @Autowired(required = false)
    UserOptMapper optMapper;
    @Autowired(required = false)
    CartMapper cartMapper;

    // pjp是目标方法的句柄
    @Around("execution(* cn.tedu.storedemo.service.impl.*.*(..))")
    public Object getOptAdvice(ProceedingJoinPoint pjp)
            throws Throwable {
        UserOpt opt=new UserOpt();
        // 填充所需的数据
        // uid
        opt.setUid(getUid());
        // pid 不同方法获取逻辑不同
        // String className=pjp.getTarget().getClass().getName(); // 目标类名
        String methodName=pjp.getSignature().getName(); // 目标方法名
        // 获取目标方法的参数
        Object[] args=pjp.getArgs();
        Integer pid=-1;
        switch (methodName){
            case "findById": // 查看商品
                pid=(Integer)args[0];
                opt.setPid(pid);
                // cid
                opt.setCid(productMapper.getCidByPid(pid));
                // type
                opt.setType(USER_OPT_TYPE_PV);
                // 写入数据库
                optMapper.insertOpt(opt);
                break;
            case "createCart": // 创建购物车
                pid=(Integer)args[0];
                opt.setPid(pid);
                // cid
                opt.setCid(productMapper.getCidByPid(pid));
                // type
                opt.setType(USER_OPT_TYPE_CART);
                // 写入数据库
                optMapper.insertOpt(opt);
                break;
            case "createOrder": // 创建订单
                Integer[] cids=(Integer[])args[1];
                // 使用cid查询对应的pid
                List<Integer> pids=cartMapper.listPidByCids(cids);
                // 使用pid查询对应的商品种类id
                List<Integer> cateIds=productMapper.listCidByPids(pids);
                // 便利生成userOpt对象，写入数据库
                // 多行记录插入 1. 拼接成一条语句 2. batch
                List<UserOpt> userOpts=new ArrayList<>();
                Integer uid=getUid();
                for(int i=0;i<pids.size();i++){
                    UserOpt userOpt=new UserOpt();
                    userOpt.setUid(uid);
                    userOpt.setPid(pids.get(i));
                    userOpt.setCid(cateIds.get(i));
                    userOpt.setType(USER_OPT_TYPE_BUY);
                    userOpts.add(userOpt);
                }
                optMapper.insertOpts(userOpts);
                break;
            default:
                break;
        }

        // 调用目标方法
        Object result=pjp.proceed();

        return result;
    }

    public Integer getUid(){
        // 通过Spring提供的RequestContextHolder获取当前用户对应的request对象
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder
                .getRequestAttributes())
                .getRequest();
        HttpSession session=request.getSession();
        UserEntity user=(UserEntity) session.getAttribute("user");
        if (user==null||user.getUid()==null){
            return 0;
        }else {
            return user.getUid();
        }
    }

}
